#pragma once
#ifndef CHATSERVICE_H
#define CHATSERVICE_H

/**
 * 服务器业务模块的头文件
 */

#include <functional>
#include <unordered_map>
#include <muduo/net/TcpServer.h>
#include <mutex>    //互斥锁

#include "json.hpp"
#include "public.hpp"
#include "redis.hpp"

//kafka
#include "kafkaConsumer.h"
#include "kafkaProducer.h"

//业务model类头文件
#include "usermodel.hpp"
#include "offlineMessageModel.hpp"
#include "friendmodel.hpp"
#include "groupmodel.hpp"



using std::function;
using std::unordered_map;

using namespace muduo;
using namespace muduo::net;

using nlohmann::json;

//表示处理消息事件回调方法的类型
using MsgHandler=function<void(const TcpConnectionPtr& conn,json& js,Timestamp time)>;


//选择消息中间件
#define USE_KAFKA //or USE_REDIS

//聊天室服务器业务类
class ChatService{
public:
    //获取单例对象
    static ChatService* getInstance();

    //处理登录业务
    void login(const TcpConnectionPtr& conn,json& js,Timestamp time);

    //处理注册业务
    void reg(const TcpConnectionPtr& conn,json& js,Timestamp time);

    //点对点聊天业务
    void oneChat(const TcpConnectionPtr& conn,json& js,Timestamp time);

    //获取某个类型的事件的处理器
    MsgHandler getHandler(EnMsgType msgID);

    //客户端异常关闭
    void clientCloseException(const TcpConnectionPtr& conn);

    //服务器异常关闭，重置客户业务方法
    void reset();

    //添加好友业务
    void addFriend(const TcpConnectionPtr& conn,json& js,Timestamp time);

    //创建群组业务
    void createGroup(const TcpConnectionPtr& conn,json& js,Timestamp time);

    //加入群组业务
    void addGroup(const TcpConnectionPtr& conn,json& js,Timestamp time);

    //群组聊天业务
    void groupChat(const TcpConnectionPtr& conn,json& js,Timestamp time);

    //处理客户端注销业务
    void loginOut(const TcpConnectionPtr& conn,json& js,Timestamp time);

#ifdef USE_REDIS
    //从redis消息队列上获取订阅的消息
    void handleRedisSubscribeMessage(int, string);
#endif


    ~ChatService();
private:
    ChatService();

    //哈希表，存放已经连接进来的客户端
    //Key:用户id  -->  Value:连接对象TcpConnectionPtr
    //WARN: 有线程安全问题，需要配合互斥锁使用
    unordered_map<int,TcpConnectionPtr> _userConnMap;

    //互斥锁，为存放用户连接的哈希表服务，保证线程安全
    std::mutex _ConnMutx;

    //消息id操作表，不同消息id对应不同的处理操作
    unordered_map<EnMsgType,MsgHandler> _msgHandlerMap;

    //数据操作类对象
    UserModel _userModel;

    //离线消息类对象
    offlineMessageModel _offlineMessageModel;

    //添加好友操作类对象
    friendModel _friendModel;

    //群组业务操作类
    GroupModel _groupmodel;

#ifdef USE_REDIS
    //Redis操作对象
    Redis _redis;
#endif //USE_REDIS

#ifdef USE_KAFKA
    KafkaConsumer* _consumer;
    KafkaProducer* _producer;

    //收到kafka消息后的回调函数
    void handleKafkaSubscribeMessage(string message);
    
#endif //USE_KAFKA

};

#endif